import { memo } from "react";
import produce from "immer";
import { useReactFlow, useStoreApi, useViewport } from "reactflow";
import { useEventListener } from "ahooks";
import { useStore, useWorkflowStore } from "./store";
import {
  WorkflowHistoryEvent,
  useNodesInteractions,
  useWorkflowHistory,
} from "./hooks";
import { CUSTOM_NODE } from "./constants";
import { getIterationStartNode } from "./utils";
import CustomNode from "./nodes";
import CustomNoteNode from "./note-node";
import { CUSTOM_NOTE_NODE } from "./note-node/constants";
import { BlockEnum } from "./types";

const CandidateNode = () => {
  const store = useStoreApi();
  const reactflow = useReactFlow();
  const workflowStore = useWorkflowStore();
  const candidateNode = useStore((s) => s.candidateNode);
  const mousePosition = useStore((s) => s.mousePosition);
  const { zoom } = useViewport();
  const { handleNodeSelect } = useNodesInteractions();
  const { saveStateToHistory } = useWorkflowHistory();

  useEventListener("click", (e) => {
    const { candidateNode, mousePosition } = workflowStore.getState();

    if (candidateNode) {
      e.preventDefault();
      const { getNodes, setNodes } = store.getState();
      const { screenToFlowPosition } = reactflow;
      const nodes = getNodes();
      const { x, y } = screenToFlowPosition({
        x: mousePosition.pageX,
        y: mousePosition.pageY,
      });
      const newNodes = produce(nodes, (draft) => {
        draft.push({
          ...candidateNode,
          data: {
            ...candidateNode.data,
            _isCandidate: false,
          },
          position: {
            x,
            y,
          },
        });
        if (candidateNode.data.type === BlockEnum.Iteration)
          draft.push(getIterationStartNode(candidateNode.id));
      });
      setNodes(newNodes);
      if (candidateNode.type === CUSTOM_NOTE_NODE)
        saveStateToHistory(WorkflowHistoryEvent.NoteAdd);
      else saveStateToHistory(WorkflowHistoryEvent.NodeAdd);

      workflowStore.setState({ candidateNode: undefined });

      if (candidateNode.type === CUSTOM_NOTE_NODE)
        handleNodeSelect(candidateNode.id);
    }
  });

  useEventListener("contextmenu", (e) => {
    const { candidateNode } = workflowStore.getState();
    if (candidateNode) {
      e.preventDefault();
      workflowStore.setState({ candidateNode: undefined });
    }
  });

  if (!candidateNode) return null;

  return (
    <div
      className="absolute z-10"
      style={{
        left: mousePosition.elementX,
        top: mousePosition.elementY,
        transform: `scale(${zoom})`,
        transformOrigin: "0 0",
      }}
    >
      {candidateNode.type === CUSTOM_NODE && (
        <CustomNode {...(candidateNode as any)} />
      )}
      {candidateNode.type === CUSTOM_NOTE_NODE && (
        <CustomNoteNode {...(candidateNode as any)} />
      )}
    </div>
  );
};

export default memo(CandidateNode);
